package org.jeecg.modules.bobo.common.api;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.ClientException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.util.AntPathMatcher;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.util.*;
import org.jeecg.modules.bobo.common.entity.LbArea;
import org.jeecg.modules.bobo.common.entity.LbSlide;
import org.jeecg.modules.bobo.common.entity.LbSlideItem;
import org.jeecg.modules.bobo.common.service.ILbAreaService;
import org.jeecg.modules.bobo.common.service.ILbDictService;
import org.jeecg.modules.bobo.common.service.ILbSlideItemService;
import org.jeecg.modules.bobo.common.service.ILbSlideService;
import org.jeecg.modules.bobo.common.util.DateUtil;
import org.jeecg.modules.bobo.common.util.ImgUtils;
import org.jeecg.modules.bobo.common.util.RandImageUtil;
import org.jeecg.modules.bobo.common.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.HtmlUtils;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.List;
import java.util.Map;

/**
 * @program: jeecg-boot-parent
 * @description: 公共api
 * @author: 三千霜
 * @create: 2020-04-17 16:46
 */
@Slf4j
@RestController
@RequestMapping("/api/common")
@Api(tags = "公共api")
@ApiSort(value = 3)
public class BoboCommonApi {
    @Autowired
    private ISysBaseAPI baseAPI;
    @Autowired
    private ILbDictService lbDictService;
    @Autowired
    private ILbAreaService lbAreaService;
    @Autowired
    private ILbSlideService lbSlideService;
    @Autowired
    private ILbSlideItemService lbSlideItemService;
    @Autowired
    private RedisUtil redisUtil;
    @Value(value="${jeecg.uploadType}")
    private String uploadType;
    @Value(value = "${jeecg.path.upload}")
    private String uploadpath;
    @Value(value = "${jeecg.bizPath}")
    private String bizPath;
    private static final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890";


    /**
     * 本地：local minio：minio 阿里：alioss
     */


    private static final Configuration configuration=new Configuration(Configuration.VERSION_2_3_27);
    private static final StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
    static {
        // 配置 freemarker configuration
        configuration.setTemplateLoader(stringTemplateLoader);
        configuration.setDefaultEncoding("UTF-8");
    }
    @RequestMapping(value = "/getConfigByCode", method = RequestMethod.GET)
    @ApiOperation("获取前端配置")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code",value = "页面配置编码",example = "group")
    })
    public Result<List<String>> getConfigByCode(@RequestParam(name="code", defaultValue="gloab") String code){
        return Result.success();
    }




    @ApiOperation(value="省市区", notes="省市区")@ApiImplicitParams({
            @ApiImplicitParam(name = "pid",value = "省传0 ")
    })
    @GetMapping(value = "/getArea")
    public Result<List<LbArea>> getArea(@RequestParam(name="pid", defaultValue="0") String pid) {
        return Result.success(lbAreaService.list(new QueryWrapper<LbArea>().lambda().eq(LbArea::getPid,pid)));
    }

    @RequestMapping(value = "/getSlideByCode", method = RequestMethod.GET)
    @ApiOperation("获取轮播图")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code",value = "幻灯片编码",example = "shouye")
    })

    public Result<List<LbSlideItem>> getSlideByCode(@RequestParam("code") String slideCode){
        String id = lbSlideService.getOne(new QueryWrapper<LbSlide>().lambda().eq(LbSlide::getCode, slideCode)).getId();
//        String id = lbSlideService.getSlideByCode(slideCode);
        List<LbSlideItem> list = lbSlideItemService.list(new QueryWrapper<LbSlideItem>().lambda().eq(LbSlideItem::getPid,id).orderByAsc(LbSlideItem::getListOrder));
        return Result.success(list);
    }
    @RequestMapping(value = "/getSlideById", method = RequestMethod.GET)
    @ApiOperation("获取轮播图")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id",value = "幻灯片id")
    })

    public Result<List<LbSlideItem>> getSlideById(@RequestParam("id") String id){
        List<LbSlideItem> list = lbSlideItemService.list(new QueryWrapper<LbSlideItem>().lambda().eq(LbSlideItem::getPid, id));
        return Result.success(list);
    }











/**
 * 反转义模板
 * @author 三千霜
 * @date 2020/4/18 11:13
 * @param: template
 * @Return java.lang.String
 * @throws

 */
    public String htmlUnescape(String template) {
        //        获取html模板 反转义
        template =   HtmlUtils.htmlUnescape(template);
        return template;

    }




    /**
     * 解析模板
     *
     * @param templateName
     * @throws IOException
     * @throws
     */
    private String processTemplate(String templateName, String templateStr,Map<String, Object> map){
        StringWriter stringWriter = new StringWriter();
        Template template = null;
        try {
            template = new Template(templateName, templateStr, configuration);
            template.process(map, stringWriter);
        } catch (TemplateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return stringWriter.toString();
    }



    /**
     * 预览图片
     * 请求地址：http://localhost:8080/common/static/{user/20190119/e1fe9925bc315c60addea1b98eb1cb1349547719_1547866868179.jpg}
     *
     * @param request
     * @param response
     */
    @ApiOperation(value="预览图片", notes="预览图片")
    @GetMapping(value = "/static/**")
    @ResponseBody
    public void previewPictures(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // ISO-8859-1 ==> UTF-8 进行编码转换
        String imgPath = extractPathFromPattern(request);
        imgPath = imgPath.replace("..", "");
        if (imgPath.endsWith(",")) {
            imgPath = imgPath.substring(0, imgPath.length() - 1);
        }
        String filePath = uploadpath + File.separator + imgPath;
        OutputStream os = null;
        try {
//        读取图片
            String type=imgPath.substring(imgPath.lastIndexOf(".")+1);
            BufferedImage image = ImageIO.read(new FileInputStream(new File(filePath)));





//            response.setContentLength(image.);
            response.setContentType("image/"+type);



            os = response.getOutputStream();

            if (image != null) {
                ImageIO.write(image, type, os);
            }
        } catch (IOException e) {
            log.error("获取图片异常{}",e.getMessage());
        } finally {
            if (os != null) {
                os.flush();
                os.close();
            }
        }
    }



    @ApiOperation(value="预览图片", notes="预览图片")
    @GetMapping(value = "/staticBase64/**")
    public String previewPicturesStaticBase64(HttpServletRequest request, HttpServletResponse response) {
        // ISO-8859-1 ==> UTF-8 进行编码转换
        String imgPath = extractPathFromPattern(request);
        return ImgUtils.ImageToBase64ByLocal(uploadpath,imgPath);
    }

    /**
     * 下载文件
     * 请求地址：http://localhost:8080/common/download/{user/20190119/e1fe9925bc315c60addea1b98eb1cb1349547719_1547866868179.jpg}
     *
     * @param request
     * @param response
     */
    @ApiOperation(value="下载文件", notes="下载文件")
    @GetMapping(value = "/download/**")
    public void download(HttpServletRequest request, HttpServletResponse response) {
        // ISO-8859-1 ==> UTF-8 进行编码转换
        String imgPath = extractPathFromPattern(request);
        // 其余处理略
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            imgPath = imgPath.replace("..", "");
            if (imgPath.endsWith(",")) {
                imgPath = imgPath.substring(0, imgPath.length() - 1);
            }
            String filePath = uploadpath + File.separator + imgPath;
            String downloadFilePath = uploadpath + File.separator + filePath;
            File file = new File(downloadFilePath);
            response.setContentType("application/force-download");// 设置强制下载不打开
            response.addHeader("Content-Disposition", "attachment;fileName=" + new String(file.getName().getBytes("UTF-8"),"iso-8859-1"));
            inputStream = new BufferedInputStream(new FileInputStream(filePath));
            outputStream = response.getOutputStream();
            byte[] buf = new byte[1024];
            int len;
            while ((len = inputStream.read(buf)) > 0) {
                outputStream.write(buf, 0, len);
            }
            response.flushBuffer();
        } catch (IOException e) {
            log.error("预览文件失败" + e.getMessage());
            // e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }

    }
    /**
     * @功能：pdf预览Iframe
     * @param modelAndView
     * @return
     */
    @RequestMapping("/pdf/pdfPreviewIframe")
    public ModelAndView pdfPreviewIframe(ModelAndView modelAndView) {
        modelAndView.setViewName("pdfPreviewIframe");
        return modelAndView;
    }

    /**
     *  把指定URL后的字符串全部截断当成参数
     *  这么做是为了防止URL中包含中文或者特殊字符（/等）时，匹配不了的问题
     * @param request
     * @return
     */
    private static String extractPathFromPattern(final HttpServletRequest request) {
        String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
        String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
        return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path);
    }


    /**
     * 生成图形验证码
     * @param response
     * @param key
     */
    @ApiOperation("获取验证码")
    @GetMapping(value = "/randomImage/{key}")
    public Result<String> randomImage(HttpServletResponse response, @PathVariable String key){
        try {
            String code = RandomUtil.randomString(BASE_CHECK_CODES,4);
            String lowerCaseCode = code.toLowerCase();
            String realKey = MD5Util.MD5Encode(lowerCaseCode+key, "utf-8");
            redisUtil.set(realKey, lowerCaseCode, 60);
            String base64 = RandImageUtil.generate(code);

            return Result.success("获取验证码成功",base64);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("获取验证码出错"+e.getMessage());
        }

    }
    /**
     * 短信验证码接口
     *
     * @param jsonObject
     * @return
     */
    @PostMapping(value = "/sms")
    public Result<String> sms(@RequestBody JSONObject jsonObject) {
        Result<String> result=new Result<>();
        String mobile = jsonObject.get("mobile").toString();
        if(oConvertUtils.isEmpty(mobile)){
            result.setMessage("手机号不允许为空！");
            result.setSuccess(false);
            return result;
        }
        Object object = redisUtil.get(mobile);
        if (object != null) {
            result.setMessage("验证码10分钟内，仍然有效！");
            result.setSuccess(false);
            return result;
        }

        //随机数
        String captcha = RandomUtil.randomNumbers(6);
        JSONObject obj = new JSONObject();
        obj.put("code", captcha);
        try {
            boolean b = false;
            b = DySmsHelper.sendSms(mobile, obj, DySmsEnum.LOGIN_TEMPLATE_CODE);
            if (b == false) {
                result.setMessage("短信验证码发送失败,请稍后重试");
                result.setSuccess(false);
                return result;
            }
            //验证码10分钟内有效
            redisUtil.set(mobile, captcha, 600);
            //update-begin--Author:scott  Date:20190812 for：issues#391
            //result.setResult(captcha);
            //update-end--Author:scott  Date:20190812 for：issues#391
            result.setSuccess(true);

        } catch (ClientException | com.aliyuncs.exceptions.ClientException e) {
            e.printStackTrace();
            result.error500(" 短信接口未配置，请联系管理员！");
            return result;
        }
        return result;
    }


    /**
     * 文件上传统一方法
     * @param request
     * @param response
     * @return
     */
    @ApiOperation(value="文件上传", notes="文件上传")
    @PostMapping(value = "/upload")
    public org.jeecg.common.api.vo.Result<?> upload(HttpServletRequest request, HttpServletResponse response) {
        org.jeecg.common.api.vo.Result<?> result = new org.jeecg.common.api.vo.Result<>();
        String savePath = "";
        String bizPath = request.getParameter("biz");
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile file = multipartRequest.getFile("file");// 获取上传文件对象
        if(oConvertUtils.isEmpty(bizPath)){
            if(CommonConstant.UPLOAD_TYPE_OSS.equals(uploadType)){
                //未指定目录，则用阿里云默认目录 upload
                bizPath = "upload";
                //result.setMessage("使用阿里云文件上传时，必须添加目录！");
                //result.setSuccess(false);
                //return result;
            }else{
                bizPath = this.bizPath;
            }
        }
        if(CommonConstant.UPLOAD_TYPE_LOCAL.equals(uploadType)){
            //针对jeditor编辑器如何使 lcaol模式，采用 base64格式存储
            String jeditor = request.getParameter("jeditor");
            if(oConvertUtils.isNotEmpty(jeditor)){
                result.setMessage(this.uploadLocal(file,bizPath));
                result.setSuccess(true);
                return result;
            }else{
                savePath = this.uploadLocal(file,bizPath);
            }
        }else{
            //update-begin-author:taoyan date:20200814 for:文件上传改造
            savePath = CommonUtils.upload(file, bizPath, uploadType);
            //update-end-author:taoyan date:20200814 for:文件上传改造
        }
        if(oConvertUtils.isNotEmpty(savePath)){
            result.setMessage(savePath);
            result.setSuccess(true);
            result.setCode(200);
        }else {
            result.setMessage("上传失败！");
            result.setSuccess(false);
        }
        return result;
    }

    /**
     * 本地文件上传
     * @param mf 文件
     * @param bizPath  自定义路径
     * @return
     */
    private String uploadLocal(MultipartFile mf,String bizPath){
        try {
            String ctxPath = uploadpath;
            String fileName = null;
            bizPath=bizPath + File.separator + DateUtil.getDate("yyyy-MM-dd")+ File.separator;
            File file = new File(ctxPath + File.separator + bizPath);
            if (!file.exists()) {
                file.mkdirs();// 创建文件根目录
            }
            String orgName = mf.getOriginalFilename();// 获取文件名
            orgName = CommonUtils.getFileName(orgName);
            if(orgName.indexOf(".")!=-1){
                fileName = System.currentTimeMillis() + orgName.substring(orgName.indexOf("."));
//                fileName = orgName.substring(0, orgName.lastIndexOf(".")) + "_" + System.currentTimeMillis() + orgName.substring(orgName.indexOf("."));
            }else{
                fileName = orgName+ "_" + System.currentTimeMillis();
            }
            String savePath = file.getPath() + File.separator + fileName;
            File savefile = new File(savePath);
            FileCopyUtils.copy(mf.getBytes(), savefile);
            String dbpath = null;
            if(oConvertUtils.isNotEmpty(bizPath)){
                dbpath = bizPath + File.separator + fileName;
            }else{
                dbpath = this.bizPath + fileName;
            }
            if (dbpath.contains("\\")) {
                dbpath = dbpath.replace("\\", "/");
            }
            return dbpath;
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return "";
    }



}
